(function (exports) {
    'use strict';

    var BAR_LENGTH = 70;

    function formatData(data) {
        function iterConfs(data, cb) {
            var dataset, dataset_r, samples, s_i, s_l, sample, sample_r;
            for (dataset in data) {
                if (data.hasOwnProperty(dataset)) {
                    dataset_r = data[dataset];
                    samples = Object.getOwnPropertyNames(dataset_r);
                    samples.sort(function cmp(x, y) {
                        return parseInt(x) - parseInt(y);
                    });
                    for (s_i = 0, s_l = samples.length; s_i < s_l; ++s_i) {
                        sample = samples[s_i];
                        sample_r = dataset_r[sample];
                        cb({dataset: dataset, sample: sample, funcs: sample_r});
                    }
                }
            }
        }

        function leftJustify(strs) {
            var i, l, s, max, k, out;
            max = -Infinity;
            for (i = 0, l = strs.length; i < l; ++i) {
                s = strs[i];
                if (s.length > max) {
                    max = s.length;
                }
            }
            out = [];
            for (i = 0, l = strs.length; i < l; ++i) {
                s = strs[i];
                for (k = s.length; k < max; ++k) {
                    s += ' ';
                }
                out.push(s);
            }
            return out;
        }

        var funcNames, funcNamesLJ, out;

        out = '';
        funcNames = {};
        iterConfs(data, function (e) {
            var n;
            for (n in e.funcs) {
                if (e.funcs.hasOwnProperty(n)) {
                    funcNames[n] = true;
                }
            }
        });
        funcNames = Object.getOwnPropertyNames(funcNames);
        funcNames.sort();
        funcNamesLJ = leftJustify(funcNames);
        iterConfs(data, function (e) {
            var id, i, l, max, mean, line, j, k, k_l, func, bar, localmin, localmax;
            id = e.dataset + '<' + e.sample + '>';
            out += id + '\n';
            max = -Infinity;
            for (i = 0, l = funcNames.length; i < l; ++i) {
                func = e.funcs[funcNames[i]];
                if (func) {
                    localmax = Math.max.apply(null, func.samples);
                    if (localmax > max) {
                        max = localmax;
                    }
                }
            }
            for (i = 0, l = funcNames.length; i < l; ++i) {
                func = e.funcs[funcNames[i]];
                if (func) {
                    mean = func.mean;
                    line = '  ' + funcNamesLJ[i] + ' ';
                    j = Math.ceil(mean * BAR_LENGTH / max);
                    localmin = Math.ceil(Math.min.apply(null, func.samples) * BAR_LENGTH / max);
                    localmax = Math.ceil(Math.max.apply(null, func.samples) * BAR_LENGTH / max);
                    bar = '';
                    for (k = 0; k < j; ++k) {
                        bar += '#';
                    }
                    for (; k < BAR_LENGTH; ++k) {
                        bar += '.';
                    }
                    // FIXME: this bar code is somewhat broken; to rewrite
                    if (localmin === 0) {
                        localmin = 1;
                    }
                    if (localmax === 0) {
                        localmax = 1;
                    }
                    if (max && localmin !== localmax) {
                        bar = 
                            bar.substring(0, localmin - 1) + 
                            (localmin === j ? '[' : '(') + 
                            bar.substring(localmin);
                        bar = 
                            bar.substring(0, localmax - 1) + 
                            (localmax === j ? ']' : ')') + 
                            bar.substring(localmax);
                    }
                    line += bar;
                    line += ' ' + mean + 'ms  (';
                    for (k = 0, k_l = func.samples.length; k < k_l; ++k) {
                        if (k) {
                            line += ' ';
                        }
                        line += func.samples[k] + 'ms';
                    }
                    line += ')';
                    out += line + '\n';
                } else {
                    out += '  ' + funcNamesLJ[i] + ' ';
                    for (k = 0; k < BAR_LENGTH; ++k) {
                        out += ' ';
                    }
                    out += ' -ms';
                    out += '\n';
                }
            }
            out += '\n';
        });

        return out;
    }

    // do the export of visible symbols
    exports.formatData = formatData;
}(typeof exports === 'undefined' ? this['show'] = {} : exports));
